﻿using System;
using System.Collections.Concurrent;
using System.Data;
using System.Management.Instrumentation;
using System.Net;
using System.Net.Sockets;
using System.ServiceModel.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Kugar.Core.Collections;
using Kugar.Core.ExtMethod;
using Kugar.Core.BaseStruct;
using System.Linq;


namespace Kugar.Core.Communications.Transfer
{
    public class RUDPServer
    {
        private Socket _socket = null;
        private int _port;
        private BufferManager _bufferManager = BufferManager.CreateBufferManager(10 * 1024 * 1024, 10 * 1024);
        private IntIndexAutoTimeoutSet<HandShakeInfo> _cacheHandShakeTempID = new IntIndexAutoTimeoutSet<HandShakeInfo>(10000);
        private IntIndexDictioanry<RUDPConnection> _cacheEnabledConnectID = new IntIndexDictioanry<RUDPConnection>(1);
        private ConcurrentDictionary<int, TransferAsyncEventArgs> _cacheAsyncResult = new ConcurrentDictionary<int, TransferAsyncEventArgs>();
        private CallbackTimer _callbackTimer = new CallbackTimer(2, 2); //共享的延迟调用器
        private short _defaultWindowSize = 5;
        private int _localBufferLength = 0;
        private int _pageSize = 0;
        private bool _enableAcceptConnect = false;
        private SocketAsyncEventArgsPool _socketPool = new SocketAsyncEventArgsPool(2000, 30);
        private TransferAsyncEventArgsRecylePool _transferAsyncPool = new TransferAsyncEventArgsRecylePool(2000, 30);
        private SocketAsyncEventArgs _receiveAsync = new SocketAsyncEventArgs();
        private TimerEx _checkSendTimeoutTimer = null;
        private TimerEx _checkConnectActiveTimer = null;
        private RUDPRevDataSegmentPool _revSegmentPool=new RUDPRevDataSegmentPool(20000,30);
        private RUDPSendDataSegmentPool _sendSegmentPool = null;
        private ACKDataPool _ackDataPool = null;
        private Thread _socketSendThread = null;
        private LinkedListEx<SocketAsyncEventArgs> _sendQueue = null;
        

        public RUDPServer(int port)
            : this(port, 5, 548)
        {
        }

        public RUDPServer(int port, short windowSize, int dataPageSize)
        {
            _sendQueue=new LinkedListEx<SocketAsyncEventArgs>();

            _cacheHandShakeTempID.ItemTimeout += CacheHandShakeTempID_ItemTimeout;

            //_checkConnectActiveTimer = new TimerEx(CheckConnectActive, 2000, null) { IsStopWhenRun = true };

            _checkSendTimeoutTimer = new TimerEx(CheckConnectSendTimeout, 2000, null) { IsStopWhenRun = true };

            _socketSendThread = new Thread(socketSendData);

            _sendSegmentPool = new RUDPSendDataSegmentPool(20000, 30, _bufferManager);

            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            _socket.Bind(new IPEndPoint(IPAddress.Any, port));

            _defaultWindowSize = windowSize;

            _pageSize = Math.Min(dataPageSize - 25, _socket.ReceiveBufferSize);

            _localBufferLength = (_pageSize * 2).ToMinInt(100);

            _ackDataPool=new ACKDataPool(2000,10,_bufferManager);

            //var buff = new byte[_localBufferLength];

            _receiveAsync.SetBuffer(_bufferManager.TakeBuffer(_localBufferLength), 0, _localBufferLength);
            _receiveAsync.Completed += SocketDataReceive;
            _receiveAsync.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            //_socket.BeginReceiveFrom(buff, 0, _localBufferLength, SocketFlags.None, ref remotePoint, SocketDataReceive, buff);

            _socket.ReceiveFromAsync(_receiveAsync);

            _checkSendTimeoutTimer.Start();

            //_socketSendThread.Start();
            //_checkConnectActiveTimer.Start();
        }



#if DEBUG

        public string Rule { set; get; }

#endif

        public void Listen()
        {
            _enableAcceptConnect = true;
            //EndPoint remotePoint=new IPEndPoint(IPAddress.Any,0);

            //var buff=_bufferManager.TakeBuffer(8192);

            //_socket.BeginReceiveFrom(buff, 0, 8192, SocketFlags.None, ref remotePoint, SocketDataReceive, buff);
        }

        public void StopListen()
        {
            _enableAcceptConnect = false;
        }

        public void Close()
        {
            StopListen();

            lock (_cacheAsyncResult)
            {
                foreach (var asyncResult in _cacheAsyncResult)
                {
                    asyncResult.Value.Error = TransferExceptionHelper.GetTransferClosedException();

                    asyncResult.Value.OnCompleted(this);
                }

                _cacheAsyncResult.Clear();
            }

            lock (_cacheHandShakeTempID)
            {
                _cacheHandShakeTempID.Clear();
            }

            lock (_cacheEnabledConnectID)
            {
                var c = _cacheEnabledConnectID.Count;

                if (c > 0)
                {
                    var au = new AutoResetEvent(false);

                    var l = new CountdownEvent(c);

                    foreach (var connect in _cacheEnabledConnectID)
                    {
                        connectBeginClose(connect.Value);

                        connect.Value.TransferClosed += (s, e) =>
                                                      {
                                                          l.Signal();
                                                      };
                    }

                    l.Wait(60000);

                    //au.WaitOne(_cacheEnabledConnectID.Count * 60000, false);

                    _cacheEnabledConnectID.Clear();
                }


            }

            _socket.Close();
        }

        public int Port { get { return _port; } }

        public bool ConnectAsync(TransferAsyncEventArgs ea, IPEndPoint remotePoint)
        {
            var bagID = _cacheHandShakeTempID.TaskItem(null);
            var buff = buildConnectRequest(bagID);

            _cacheAsyncResult.AddOrUpdate(bagID, ea);
            _cacheHandShakeTempID.AddOrUpdate(bagID, new HandShakeInfo(0, remotePoint, RUDPConnectStatus.Syn_Send, bagID));

            var sea = _transferAsyncPool.Take();

            sea.SetBuffer(buff.Array, buff.Offset, buff.Count);
            sea.Completed += returnBuffer;

            if(!SendData(sea, remotePoint))
            {
                sea.Dispose();

            }

            //SendData(buff.Array, buff.Offset, buff.Count, remotePoint, null, null);

            return true;
        }

        //public INetTransfer ConnectTo(IPEndPoint remotePoint)
        //{
        //    IAsyncResult iar;
        //    INetTransfer conn = null;
        //    Exception error = null;
        //    iar = BeginConnectTo(remotePoint, (o) =>
        //                                          {
        //                                              try
        //                                              {
        //                                                    conn = EndConnectTo(o);
        //                                              }
        //                                              catch (Exception ex)
        //                                              {
        //                                                  error = ex;
        //                                              }

        //                                          }, null);

        //    if(iar.AsyncWaitHandle.WaitOne(30000, false))
        //    {
        //        return conn;
        //    }
        //    else
        //    {
        //        if (error==null)
        //        {
        //            throw new TimeoutException("连接超时");
        //        }
        //        else
        //        {
        //            throw error;
        //        }

        //    }


        //}

        //public IAsyncResult BeginConnectTo(IPEndPoint remotePoint, AsyncCallback callback, object state)
        //{
        //    var bagID = _cacheHandShakeTempID.TaskItem(null);
        //    var buff = buildConnectRequest(bagID);

        //    var iar = new RUDPConnectAsyncResult(this, bagID, callback, state);

        //    _cacheAsyncResult.AddOrUpdate(bagID, iar);
        //    _cacheHandShakeTempID.AddOrUpdate(bagID,new HandShakeInfo(0,remotePoint,RUDPConnectStatus.Syn_Send,bagID));

        //    SendData(buff.Array, buff.Offset, buff.Count, remotePoint, null, null);

        //    return iar;
        //}

        //public INetTransfer EndConnectTo(IAsyncResult iar)
        //{
        //    Exception error = null;

        //    var conn = EndConnectTo(iar, ref error);

        //    if (error!=null)
        //    {
        //        throw error;
        //    }
        //    else
        //    {
        //        return conn;
        //    }

        //    //if (!(iar is RUDPConnectAsyncResult))
        //    //{
        //    //    return null;
        //    //}

        //    //var asyncResult = (RUDPConnectAsyncResult)iar;

        //    //var connectID = asyncResult.ConnectID;

        //    //if (_cacheAsyncResult.ContainsKey(asyncResult.BagID))
        //    //{
        //    //    _cacheAsyncResult.Remove(asyncResult.BagID);

        //    //}

        //    //RUDPConnectConfig config = _cacheEnabledConnectID[connectID];

        //    //if (config != null)
        //    //{
        //    //    return config.Item;
        //    //}
        //    //else
        //    //{
        //    //    throw new InstanceNotFoundException("未存在指定的链接");
        //    //}


        //    //foreach (var rudpLink in _cacheConnectList)
        //    //{
        //    //    if (rudpLink.ContansConnection(connectID))
        //    //    {
        //    //        return rudpLink[connectID];
        //    //    }
        //    //}

        //    //throw new InstanceNotFoundException("未存在指定的链接");
        //}

        //public INetTransfer EndConnectTo(IAsyncResult iar, ref Exception error)
        //{
        //    if (!(iar is RUDPConnectAsyncResult))
        //    {
        //        return null;
        //    }

        //    var asyncResult = (RUDPConnectAsyncResult)iar;


        //    if (asyncResult.HasError)
        //    {
        //        error = asyncResult.Error;
        //        return null;
        //    }
        //    else
        //    {
        //        var connectID = asyncResult.ConnectID;



        //        if (_cacheAsyncResult.ContainsKey(asyncResult.BagID))
        //        {
        //            //_cacheAsyncResult.Remove(asyncResult.BagID);
        //        }

        //        RUDPConnection config = null;

        //        if (_cacheEnabledConnectID.TryGetValue(connectID,out config))
        //        {
        //            return config._item;
        //        }
        //        else
        //        {
        //            error = new InstanceNotFoundException("未存在指定的链接");
        //            return null;
        //        }
        //         //_cacheEnabledConnectID[connectID];

        //        //if (config != null)
        //        //{

        //        //}
        //        //else
        //        //{

        //        //}
        //    }



        //}
        


        public event EventHandler<RemoteRequestConnectEventArgs> ConnectRequest;

        public event EventHandler<RemoteConenctSuccessEventArgs> ConnectSuccessed;

        public event EventHandler<RUDPDisconnectedEventArgs> Disconnected;

        public event EventHandler<TransferAsyncEventArgs> BeforceSendData;

        public event EventHandler<TransferAsyncEventArgs> AfterSendData;

        public event EventHandler<TransferAsyncEventArgs> AfterReceiveData;

        private bool SendData(TransferAsyncEventArgs ea, IPEndPoint remotePoint)
        {
            if (ea.Buffer == null)
            {
                throw new ArgumentNullException("ea.Buffer");
            }

            SocketFlags flags;

            if (remotePoint.Address == IPAddress.Broadcast)
            {
                flags = SocketFlags.Broadcast;
            }
            else
            {
                flags = SocketFlags.None;
            }

            var socketEa = _socketPool.Take();

            socketEa.SetBuffer(ea.Buffer, ea.Offset, ea.Count);
            socketEa.SocketFlags = flags;
            socketEa.RemoteEndPoint = remotePoint;
            socketEa.UserToken = ea;

            socketEa.Completed += sendDataCompleted;

            bool retValue=true;

            try
            {
                //_sendQueue.AddLast(socketEa);

                retValue = _socket.SendToAsync(socketEa);

                if (!retValue)
                {
                    if (socketEa.SocketError != SocketError.Success)
                    {
                        ea.Error = TransferExceptionHelper.GetTransferException(socketEa.SocketError.ToString());
                    }

                    socketEa.Completed -= sendDataCompleted;

                    socketEa.SocketFlags = SocketFlags.None;
                    socketEa.RemoteEndPoint = null;
                    socketEa.UserToken = null;

                    socketEa.Dispose();
                }



            }
            catch (Exception error)
            {
                retValue = false;
                ea.Error = error;
            }

            return retValue;


            //_socket.BeginSendTo(data, offset, count, flags, remotePoint,
            //                                                                (iar) =>
            //                                                                {
            //                                                                    try
            //                                                                    {
            //                                                                        _socket.EndSendTo(iar);
            //                                                                    }
            //                                                                    catch (Exception)
            //                                                                    {
            //                                                                    }

            //                                                                    if (callback != null)
            //                                                                    {
            //                                                                        callback(state);
            //                                                                    }

            //                                                                }, null);

        }


        #region "事件引发"

        internal bool OnConnectRequest(IPEndPoint remotePoint)
        {
            if (!_enableAcceptConnect)
            {
                return false;
            }

            if (ConnectRequest != null)
            {
                var e = new RemoteRequestConnectEventArgs(remotePoint, null);
                ConnectRequest(this, e);

                return e.IsEnableConnect;
            }
            else
            {
                return false;
            }
        }

        internal void OnConnectSuccess(RUDPConnectionInternal item)
        {
            if (ConnectSuccessed != null)
            {
                Events.EventHelper.RaiseAsync(ConnectSuccessed, this, new RemoteConenctSuccessEventArgs(item));
            }
        }

        internal void OnDisconnected(RUDPDisconnectedEventArgs e)
        {
            RUDPConnection conn;

            if (_cacheEnabledConnectID.TryGetValue(e.ConnectID, out conn))
            {
                conn.AfterDataSended -= OnAfterSendData;
                conn.BeforceDataSend -= OnBeforceSendData;
                conn.AfterDataReceived -= OnDataReceiveCompleted;

                conn.SendClear -= handleSendClear;

                conn.SendItemRequest -= OnDataSegmentSend;
                conn.ACKSending -=  OnACKSending;

                _cacheEnabledConnectID.ReturnValue(e.ConnectID);

                Events.EventHelper.RaiseAsync(Disconnected, this, e);
            }



        }

        internal void OnDataReceiveCompleted(object sender, TransferAsyncEventArgs e)
        {
            Events.EventHelper.Raise(AfterReceiveData, this, e);
        }

        internal void OnBeforceSendData(object sender, TransferAsyncEventArgs e)
        {
            Events.EventHelper.Raise(BeforceSendData, this, e);
        }

        internal void OnAfterSendData(object sender, TransferAsyncEventArgs e)
        {
            Events.EventHelper.Raise(AfterSendData, this, e);
        }

        #endregion

        //负责处理Socket的数据接收操作
        private void SocketDataReceive(object sender, SocketAsyncEventArgs e)
        {
            var buff = e.Buffer;
            var readCount = e.BytesTransferred;
            var remotePoint = (IPEndPoint)e.RemoteEndPoint;
            var error = e.SocketError;

            e.RemoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
            e.SetBuffer(_bufferManager.TakeBuffer(_localBufferLength), 0, _localBufferLength);

            try
            {
                if (!_socket.ReceiveFromAsync(e))
                {
                    SocketDataReceive(this,e);
                }
            }
            catch (Exception)
            {
                
            }

            

            //if (buff[1]==0xf2)
            //{
                
            //}

            if (error == SocketError.Success && readCount > 4)
            {
                var cmdByte = buff[1];

                if (buff.GetCRCCode(0, readCount) != 0 || //CRC校验错误
                   !CheckCmd(buff, 0, readCount))  //指令码不在范围之内
                {
                    _bufferManager.ReturnBuffer(buff);
                    return;
                }


                var cmd = (RUDPCmd)cmdByte;

                switch (cmd)
                {
                    case RUDPCmd.HandShake_ConnectRequest:
                    case RUDPCmd.HandShake_ConnectResponse:
                    case RUDPCmd.HandShake_ConnectSuccess:
                    case RUDPCmd.HandShake_ConnectSuccessACK:
                        {
                            HandShakeReceive(cmd, buff, 0, readCount, remotePoint);
                            break;
                        }
                    case RUDPCmd.Data:
                    case RUDPCmd.DataACK:
                        {
                            var connectID = BitConverter.ToInt32(buff, 2);

                            RUDPConnection conn;

                            if (_cacheEnabledConnectID.TryGetValue(connectID, out conn) && conn!=null)
                            {
                                if (conn.Status== RUDPConnectStatus.TransferWait)
                                {
                                    conn.Status=RUDPConnectStatus.ESTABLISHED;
                                }

                                conn.OnDataReceive(cmd, buff, 0, readCount);
                            }
                            else
                            {
                                
                            }

                            break;
                        }
                    case RUDPCmd.HandShake_Fin:
                    case RUDPCmd.HandShake_FinSendClear:
                    case RUDPCmd.HandShake_FinSendClear_ACK:
                    case RUDPCmd.HandShake_Fin_ACK:
                        {
                            var connectID = BitConverter.ToInt32(buff, 2);

                            RUDPConnection conn;

                            if (_cacheEnabledConnectID.TryGetValue(connectID, out conn) && conn != null)
                            {
                                handleCloseConnection(cmd, buff, 0, readCount, conn);
                            }
                            else
                            {

                            }

                            break;
                        }

                    case RUDPCmd.KeepActive:
                    case RUDPCmd.KeepActive_ACK:
                        {
                            var connectID = BitConverter.ToInt32(buff, 2);

                            RUDPConnection conn;
                            if (_cacheEnabledConnectID.TryGetValue(connectID, out conn) && conn != null)
                            {
                                handleKeepAlive(cmd, buff, 0, readCount, conn);
                            }
                            else
                            {

                            }

                        }
                        break;

                    default:
                        {
                            break;
                        }
                }
            }
            else
            {
                
            }

            //_bufferManager.ReturnBuffer(buff);


        }

        private void OnDataSegmentSend(RUDPConnection conn, RUDPSendDataSegment segment)
        {
            if (segment.Count<=0 || segment.Data==null)
            {
                return;
            }

            var t = _transferAsyncPool.Take();

            ArraySegment<byte> dt ;

            try
            {
                dt = segment.BuildToBytes();
            }
            catch (Exception)
            {
                t.Dispose();
                return;
            }


            t.SetBuffer(dt.Array, dt.Offset, dt.Count);

            t.Completed += (s, e) =>
                               {
                                   segment.SendTime = DateTime.Now;
                                   e.Dispose();

                                   _bufferManager.ReturnBuffer(dt.Array);
                               };

            SendData(t, conn.RemotePoint);

        }

        private void OnACKSending(RUDPConnection conn,short ackIndex)
        {

            //var t = _ackDataPool.Take();

            var data=_ackDataPool.BuildBytes(conn.ConnectID, new[] {ackIndex});

            var ea = _transferAsyncPool.Take();

            ea.SetBuffer(data.Array,data.Offset,data.Count);

            ea.Completed += returnBuffer;

            if(!SendData(ea, conn.RemotePoint))
            {
                _bufferManager.ReturnBuffer(ea.Buffer);
                ea.Dispose();
            }
        }

        #region "连接握手处理"

        private void HandShakeReceive(RUDPCmd cmd, byte[] data, int offset, int count, IPEndPoint remotePoint)
        {
            TransferAsyncEventArgs ea=null;

            switch (cmd)
            {
                case RUDPCmd.HandShake_ConnectRequest:   //客户端发送，服务器端处理
                    {
                        if (!_enableAcceptConnect)
                        {
                            return;
                        }

                        var srcBagID = BitConverter.ToInt32(data, offset + 2);
                        int connectID = 0;
                        var shakeInfo = _cacheHandShakeTempID[srcBagID];
                        bool isNeedSend = false;

                        if (shakeInfo != null && shakeInfo.Status == RUDPConnectStatus.Syn_Rev)
                        {
                            connectID = shakeInfo.ConnectID;
                            isNeedSend = true;
                        }
                        else if (OnConnectRequest(remotePoint))
                        {   
                            connectID = _cacheEnabledConnectID.TaskItem(null);
                            _cacheHandShakeTempID.AddOrUpdate(srcBagID, new HandShakeInfo(connectID, remotePoint, RUDPConnectStatus.Syn_Rev, srcBagID));
                            isNeedSend = true;
                        }

                        if (isNeedSend)
                        {
                            _cacheHandShakeTempID.ActiveItem(srcBagID);
                            var buff = buildConnectResponse(connectID, srcBagID);

                            if (buff.Array != null)
                            {
                                ea = _transferAsyncPool.Take();

                                ea.SetBuffer(buff.Array, buff.Offset, buff.Count);
                                //ea.Completed += returnBuffer;

                                //if(!SendData(ea, remotePoint))
                                //{
                                //    _bufferManager.ReturnBuffer(ea.Buffer);
                                //    ea.Dispose();
                                //}

                                //SendData(buff.Array, buff.Offset, buff.Count, remotePoint, s => _bufferManager.ReturnBuffer(buff.Array), null);

                            }


                        }
                    }


                    break;

                case RUDPCmd.HandShake_ConnectResponse:  //服务器端发送，客户端处理
                    {
                        //当客户端接收到该指令时，表示服务器端连接接受
                        var srcBagID = BitConverter.ToInt32(data, offset + 2);
                        var connectID = BitConverter.ToInt32(data, offset + 6);

                        RUDPConnection connectConfig = null;

                        if (_cacheEnabledConnectID.ContainsID(connectID))
                        {
                            connectConfig = _cacheEnabledConnectID[connectID];
                        }

                        var shakeInfo = _cacheHandShakeTempID[srcBagID];
                        var isNeedSend = false;

                        if ((!_cacheEnabledConnectID.ContainsID(connectID)) &&
                             (shakeInfo != null && shakeInfo.Status == RUDPConnectStatus.Syn_Send) &&
                             _cacheAsyncResult.ContainsKey(srcBagID)
                            )
                        {
                            isNeedSend = true;
                            var pageDataSize = BitConverter.ToInt32(data, offset + 10);
                            var windowSize = Math.Min(data[offset + 14], _defaultWindowSize);
                            shakeInfo.ConnectID = connectID;

                            var transfer = addNewConnection(connectID, remotePoint, pageDataSize, windowSize);

                            transfer.Status = RUDPConnectStatus.TransferWait;

                            _cacheHandShakeTempID.ReturnValue(srcBagID);

                            //异步回调
                            var asyncEventArgs = _cacheAsyncResult[srcBagID];

                            if (asyncEventArgs != null)
                            {
                                asyncEventArgs.Transfer = transfer._item;

                                asyncEventArgs.OnCompleted(this);
                            }
                        }
                        else if (connectConfig != null && connectConfig.Status == RUDPConnectStatus.TransferWait)
                        {
                            isNeedSend = true;
                        }

                        if (isNeedSend)
                        {
                            _cacheHandShakeTempID.ActiveItem(srcBagID);
                            var buff = buildConnectSuccess(data, offset, count);

                            if (buff.Array != null)
                            {
                                ea = _transferAsyncPool.Take();

                                ea.SetBuffer(buff.Array, buff.Offset, buff.Count);
                                //ea.Completed += returnBuffer;

                                ////SendData(ea, remotePoint);

                                //if (!SendData(ea, remotePoint))
                                //{
                                //    _bufferManager.ReturnBuffer(ea.Buffer);
                                //    ea.Dispose();
                                //}
                            }

                            //SendData(buff.Array, buff.Offset, buff.Count, remotePoint, (s) => _bufferManager.ReturnBuffer(buff.Array), null);
                        }

                    }
                    break;
                case RUDPCmd.HandShake_ConnectSuccess:  //客户端发送，服务器端处理
                    //服务器端接收到该指令后，表示服务器端连接完成
                    {
                        if (!_enableAcceptConnect)
                        {
                            return;
                        }

                        var connectID = BitConverter.ToInt32(data, offset + 6);
                        var srcBagID = BitConverter.ToInt32(data, offset + 2);

                        HandShakeInfo shakeInfo = _cacheHandShakeTempID[srcBagID];

                        if ((_cacheEnabledConnectID.ContainsID(connectID) && _cacheEnabledConnectID[connectID] == null) &&
                           (shakeInfo != null && shakeInfo.ConnectID == connectID && shakeInfo.Status == RUDPConnectStatus.Syn_Rev)
                            )
                        {
                            _cacheHandShakeTempID.ActiveItem(srcBagID);

                            RUDPConnection conn = null;

                            if(_cacheEnabledConnectID.TryGetValue(connectID,out conn) && conn==null)
                            {
                                var revPageSize = BitConverter.ToInt32(data, offset + 10);
                                var windowSize = (short)data[offset + 14];

                                var rudp = addNewConnection(connectID, remotePoint, revPageSize, windowSize);


                                if (rudp != null)
                                {
                                    _cacheHandShakeTempID.ReturnValue(srcBagID);

                                    OnConnectSuccess(rudp._item);
                                }
                            }

                            var repData = buildConnectSuccessACK(connectID, srcBagID);

                            if (repData.Array!=null)
                            {
                                ea = _transferAsyncPool.Take();

                                ea.SetBuffer(repData.Array, repData.Offset, repData.Count);
                                //ea.Completed += returnBuffer;

                                ////SendData(ea, remotePoint);

                                //if (!SendData(ea, remotePoint))
                                //{
                                //    _bufferManager.ReturnBuffer(ea.Buffer);
                                //    ea.Dispose();
                                //}
                            }

                        }

                        break;
                    }
                case  RUDPCmd.HandShake_ConnectSuccessACK:  //服务器端发送,,客户端处理,后表示连接正式建立
                    {
                        

                        var connectID = BitConverter.ToInt32(data, offset + 2);
                        //var srcBagID = BitConverter.ToInt32(data, offset + 2);

                        //HandShakeInfo shakeInfo = _cacheHandShakeTempID[srcBagID];

                        RUDPConnection rudpConnect = null;

                        if (_cacheEnabledConnectID.TryGetValue(connectID,out rudpConnect))
                        {
                            rudpConnect.Status= RUDPConnectStatus.ESTABLISHED;
                        }

                        break;

                        //if ((_cacheEnabledConnectID.ContainsID(connectID) && _cacheEnabledConnectID[connectID] == null) &&
                        //       (shakeInfo != null && shakeInfo.ConnectID == connectID && shakeInfo.Status == RUDPConnectStatus.Syn_Rev)
                        //   )
                        //{
                        //    _cacheHandShakeTempID.ActiveItem(srcBagID);

                        //    if (!_cacheEnabledConnectID.ContainsID(connectID))
                        //    {
                        //        var revPageSize = BitConverter.ToInt32(data, offset + 10);
                        //        var windowSize = (short)data[offset + 14];

                        //        var rudp = addNewConnection(connectID, remotePoint, revPageSize, windowSize);

                        //        if (rudp != null)
                        //        {
                        //            _cacheHandShakeTempID.ReturnValue(srcBagID);

                        //            OnConnectSuccess(rudp);
                        //        }
                        //    }

                        //}

                        //break;
                    }

                default:
                    break;
            }

            if (ea!=null)
            {
                ea.Completed += returnBuffer;

                if (!SendData(ea, remotePoint))
                {
                    _bufferManager.ReturnBuffer(ea.Buffer);
                    ea.Dispose();
                }                
            }



            _bufferManager.ReturnBuffer(data);
        }

        private void ReTryConnectTo(int bagID)
        {
            //var bagID = _cacheHandShakeTempID.TaskItem(null);
            var buff = buildConnectRequest(bagID);

            HandShakeInfo handShake = _cacheHandShakeTempID[bagID];

            if (handShake == null)
            {
                return;
            }

            var sea = _transferAsyncPool.Take();

            sea.SetBuffer(buff.Array, buff.Offset, buff.Count);
            sea.Completed += returnBuffer;

            if(!SendData(sea, handShake.RemotePoint))
            {
                sea.Dispose();
            }
        }

        private ArraySegment<byte> buildConnectResponse(int connectID, int srcID)
        {
            var buff = _bufferManager.TakeBuffer(17);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectResponse);
            bs.Write(BitConverter.GetBytes(srcID));
            bs.Write(BitConverter.GetBytes(connectID));
            bs.Write(BitConverter.GetBytes(_pageSize));
            bs.WriteByte((byte)_defaultWindowSize);
            bs.Write(buff.GetCRCCodeBytes(0, 15));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 17);
        }

        private ArraySegment<byte> buildConnectRequest(int bagID)
        {
            var buff = _bufferManager.TakeBuffer(9);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectRequest);
            bs.Write(BitConverter.GetBytes(bagID));
            bs.WriteByte((byte)_defaultWindowSize);
            bs.Write(buff.GetCRCCodeBytes(0, 7));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 9);
        }

        /// <summary>
        ///     
        /// </summary>
        /// <param name="revData">接收到的HandShake_ConnectResponse指令</param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        private ArraySegment<byte> buildConnectSuccess(byte[] revData, int offset, int count)
        {
            var bagID = BitConverter.ToInt32(revData, offset + 2);
            var connectID = BitConverter.ToInt32(revData, offset + 6);
            var serverPageSize = BitConverter.ToInt32(revData, offset + 10);
            var serverWindowSize = (short)revData[offset + 14];

            var revPageSize = Math.Min(serverPageSize, _pageSize);
            var windowSize = (short)Math.Min(serverWindowSize, _defaultWindowSize);

            var buff = _bufferManager.TakeBuffer(17);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectSuccess);
            bs.Write(BitConverter.GetBytes(bagID));
            bs.Write(BitConverter.GetBytes(connectID));
            bs.Write(revPageSize);
            bs.WriteByte((byte)windowSize);
            bs.Write(buff.GetCRCCodeBytes(0, 15));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 17);
        }

        private ArraySegment<byte> buildConnectSuccessACK(int connectID,int srcID)
        {
            var buff = _bufferManager.TakeBuffer(8);

            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.HandShake_ConnectSuccessACK);
            bs.Write(BitConverter.GetBytes(connectID));
            bs.Write(buff.GetCRCCodeBytes(0, 6));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 8);
        }

        private RUDPConnection addNewConnection(int connectID, IPEndPoint remotePoint, int pageSize, short windowSize)
        {
            var connectConfig = new RUDPConnection(this, connectID, windowSize, pageSize, _port, remotePoint, _bufferManager, _revSegmentPool, _sendSegmentPool,_ackDataPool);

            if (_cacheEnabledConnectID.TryAdd(connectID, connectConfig) || _cacheEnabledConnectID.TryUpdate(connectID,connectConfig,null))
            {

                connectConfig.SendClear += handleSendClear;
                connectConfig.BeginClosing += connectBeginClose;

                connectConfig.BeforceDataSend += OnBeforceSendData;
                connectConfig.AfterDataSended += OnAfterSendData;
                connectConfig.AfterDataReceived += OnDataReceiveCompleted;

                connectConfig.SendItemRequest += OnDataSegmentSend;
                connectConfig.ACKSending += OnACKSending;

                return connectConfig;
            }
            else
            {
                return null;
            }

        }

        #endregion

        #region "处理连接断开"

        private void connectBeginClose(RUDPConnection conn)
        {
            var data = conn.buildFinRequest();

            var ea = _transferAsyncPool.Take();

            ea.SetBuffer(data.Array, data.Offset, data.Count);
            ea.Completed += returnBuffer;

            SendData(ea, conn.RemotePoint);

            conn.Status = RUDPConnectStatus.Fin_Wait1;
        }

        private void handleCloseConnection(RUDPCmd cmd, byte[] data, int offset, int count, RUDPConnection conn)
        {
            switch (cmd)
            {
                case RUDPCmd.HandShake_Fin:  //被动关闭方接收到关闭指令后
                    {
                        conn.Status = RUDPConnectStatus.Close_Wait;

                        var respData = conn.buildFinRequestACK();

                        var ea = _transferAsyncPool.Take();

                        ea.SetBuffer(respData.Array, respData.Offset, respData.Count);
                        ea.Completed += returnBuffer;

                        SendData(ea, conn.RemotePoint);

                        conn.Stop();
                        break;
                    }

                case RUDPCmd.HandShake_Fin_ACK:
                    {
                        if (conn.Status == RUDPConnectStatus.Fin_Wait1)
                        {
                            conn.Status = RUDPConnectStatus.Fin_Wait2;
                        }
                    }

                    break;
                case RUDPCmd.HandShake_FinSendClear:  //主动关闭方接收到被动关闭方该消息时，表示被动方所有数据已经发送完毕，可以关闭连接
                    //发送ACK包
                    if (conn.Status == RUDPConnectStatus.Fin_Wait2 || conn.Status == RUDPConnectStatus.Time_Wait || conn.Status == RUDPConnectStatus.Fin_Wait1)
                    {
                        //有可能HandShake_FinSendClear与HandShake_Fin_ACK同时发出并先后被主动关闭方接收到
                        if (conn.Status == RUDPConnectStatus.Fin_Wait2 || conn.Status == RUDPConnectStatus.Fin_Wait1)
                        {
                            conn.StopReceiveQueue();//; _revQueue.Stop();
                            conn.Status = RUDPConnectStatus.Time_Wait;

                            _callbackTimer.Call(120000, (t) =>
                                                            {
                                                                _cacheEnabledConnectID.ReturnValue(conn.ConnectID);
                                                                conn.Close();
                                                                OnDisconnected(new RUDPDisconnectedEventArgs(conn._item, null));
                                                                
                                                            }, null);
                        }

                        var dt = conn.buildFinSendClearACK();

                        var ea = _transferAsyncPool.Take();

                        ea.SetBuffer(dt.Array, dt.Offset, dt.Count);
                        ea.Completed += returnBuffer;

                        SendData(ea, conn.RemotePoint);
                    }
                    break;
                case RUDPCmd.HandShake_FinSendClear_ACK:
                    {
                        if (conn.Status == RUDPConnectStatus.Last_ACK)
                        {
                            conn.Status = RUDPConnectStatus.Closed;
                            conn.Close();
                            OnDisconnected(new RUDPDisconnectedEventArgs(conn._item, null));
                        }

                    }
                    break;
            }

            _bufferManager.ReturnBuffer(data);
        }

        private void handleSendClear(RUDPConnection conn)
        {
            if (conn.Status == RUDPConnectStatus.Close_Wait)
            {
                var dt = conn.buildFinSendClear();

                var ea = _transferAsyncPool.Take();

                ea.SetBuffer(dt.Array, dt.Offset, dt.Count);
                ea.Completed += returnBuffer;

                SendData(ea, conn.RemotePoint);

                conn.Status = RUDPConnectStatus.Last_ACK;

                _callbackTimer.Call(20000, (o) =>
                {
                    if (conn.Status == RUDPConnectStatus.Last_ACK)
                    {
                        handleSendClear(conn);
                    }
                });
            }
        }

        #endregion

        #region "处理心跳包"

        private void SendKeepAlive(RUDPConnection conn)
        {
            var t = conn.getKeepAlive();

            var ea = _transferAsyncPool.Take();

            ea.SetBuffer(t, 0, t.Length);

            SendData(ea, conn.RemotePoint);

        }

        private void handleKeepAlive(RUDPCmd cmd, byte[] data, int offset, int count, RUDPConnection conn)
        {
            if (cmd == RUDPCmd.KeepActive)
            {
                if (conn.isKeepAliveSuccess(data, offset, count))
                {
                    //conn.LastDataTransfered = DateTime.Now;
                    conn.Activate();
                }
            }
            else if (cmd == RUDPCmd.KeepActive_ACK)
            {
                conn.Activate();
                //conn.LastDataTransfered = DateTime.Now;
            }
        }

        #endregion

        private void socketSendData(object state)
        {
            while (true)
            {
                var t = _sendQueue.RemoveFirst(false);

                if (t!=null && t.Value!=null)
                {
                    var item = t.Value;

                    var retValue = _socket.SendToAsync(item);


                    if (!retValue)
                    {
                        if (item.SocketError != SocketError.Success)
                        {
                            var ea = (TransferAsyncEventArgs)item.UserToken;
                            ea.Error = TransferExceptionHelper.GetTransferException(item.SocketError.ToString());
                        }

                        item.Completed -= sendDataCompleted;

                        item.SocketFlags = SocketFlags.None;
                        item.RemoteEndPoint = null;
                        item.UserToken = null;

                        item.Dispose();
                    }
                }
                else
                {
                    Thread.Sleep(200);
                }
            }


        }

        private void sendDataCompleted(object sender, SocketAsyncEventArgs e)
        {
            e.Completed -= sendDataCompleted;

            var temp = (SocketAsyncEventArgsEx)e;

            if (temp != null)
            {
                using (temp)
                {
                    var ea = (TransferAsyncEventArgs)temp.UserToken;

                    ea.OnCompleted(ea.Transfer);
                }
            }

        }

        private void returnBuffer(object sender, TransferAsyncEventArgs e)
        {
            using (e)
            {
                _bufferManager.ReturnBuffer(e.Buffer);
            }
        }

        private bool CheckCmd(byte[] data, int offset, int count)
        {
            bool retValue = false;
            switch (data[offset])
            {
                case 1:
                    {
                        var cmdByte = data[offset + 1];
                        if ((cmdByte >= 0x00 && cmdByte <= 0x03) ||
                           (cmdByte >= 0xF0 && cmdByte <= 0xF7) ||
                           (cmdByte >= 0xE0 && cmdByte <= 0xE1))  //指令码不在范围之内                        
                        {
                            retValue = true;
                        }
                        else
                        {
                            
                        }
                    }
                    break;

            }

            return retValue;
        }

        private void CheckConnectSendTimeout(object state)
        {
            if (_cacheEnabledConnectID.Count>0)
            {
                Parallel.ForEach(_cacheEnabledConnectID, (s) =>
                                                             {
                                                                 if (s.Value!=null)
                                                                 {
                                                                     s.Value.CheckSendTimeout();
                                                                 }
                                                             });                
            }


        }

        private void CheckConnectActive(object state)
        {
            var now = DateTime.Now.AddSeconds(-5).Ticks;

            Parallel.ForEach(_cacheEnabledConnectID, (s) =>
                                                         {
                                                             var item = s.Value;

                                                             if (item!=null)
                                                             {
                                                                 if (item.Status== RUDPConnectStatus.ESTABLISHED && item.LastDataTransfered > now)
                                                                 {
                                                                     SendKeepAlive(item);
                                                                 }                                                                 
                                                             }
                                                         });
        }

        private void CacheHandShakeTempID_ItemTimeout(object sender, IntIndexAutoTimeoutSetTimeoutEventArgs<int, HandShakeInfo> e)
        {
            return;
            ;

            if (e.TimeoutCount > 5) //超时次数大于5
            {
                TransferAsyncEventArgs iar = null;

                if (_cacheAsyncResult.TryGetValue(e.Value.ID, out iar))
                {
                    //_cacheAsyncResult.Remove(e.Value.ID);
                    _cacheHandShakeTempID.ReturnValue(e.Value.ID);
                    e.Value.RemotePoint = null;
                    e.Value.ConnectID = 0;
                    e.Value.ID = 0;

                    iar.Error = new TimeoutException("连接超时或远程主机未响应");
                    iar.OnCompleted(this);

                    //ThreadPool.QueueUserWorkItem((o) => ((RUDPConnectAsyncResult)o).Execute(new TimeoutException("连接超时或远程主机未响应")), iar);

                    return;
                }
            }

            if (e.Value.Status == RUDPConnectStatus.Syn_Send)
            {
                if (_cacheHandShakeTempID.ActiveItem(e.Value.ID, false))
                {
                    //var t = buildConnectRequest(e.ItemKey);   

                    //var ea = _transferAsyncPool.Take();

                    //ea.SetBuffer(t.Array,t.Offset,t.Count);
                    //ea.Completed += returnBuffer;

                    //SendData(ea, e.Value.RemotePoint);

                    ReTryConnectTo(e.Value.ID);

                    //SendData(t.Array, t.Offset, t.Count, e.Value.RemotePoint, (o) => _bufferManager.ReturnBuffer((byte[])o), t.Array);
                }

            }
            else if (e.Value.Status == RUDPConnectStatus.Syn_Rev)
            {
                if (_cacheHandShakeTempID.ActiveItem(e.Value.ID, false))
                {
                    var t = buildConnectResponse(e.ItemKey, e.Value.ID);

                    var ea = _transferAsyncPool.Take();

                    ea.SetBuffer(t.Array, t.Offset, t.Count);
                    ea.Completed += returnBuffer;

                    SendData(ea, e.Value.RemotePoint);

                    //SendData(t.Array, t.Offset, t.Count, e.Value.RemotePoint, (o) => _bufferManager.ReturnBuffer((byte[])o), t.Array);
                }
            }
            else
            {
                _cacheHandShakeTempID.ReturnValue(e.Value.ID);
            }

        }


        private class HandShakeInfo
        {
            public HandShakeInfo(int connectId, IPEndPoint remotePoint, RUDPConnectStatus status, int id)
            {
                ConnectID = connectId;
                RemotePoint = remotePoint;
                Status = status;
                ID = id;
            }

            public int ConnectID;
            public IPEndPoint RemotePoint;
            public RUDPConnectStatus Status;
            public int ID;
        }
    }

    internal class ACKDataPool:RecyclablePool<ACKData>
    {
        private BufferManager _bufferManage = null;

        public ACKDataPool(int maxLength, int minLength, BufferManager bufferManager):base(maxLength,minLength)
        {
            _bufferManage = bufferManager;

            base.Init();
        }

        #region Overrides of RecyclablePool<ACKData>

        /// <summary>
        ///     构建一个新的对象,该函数必须由继承的类实现
        /// </summary>
        /// <returns></returns>
        protected override ACKData CreateRecyclableObject()
        {
            return new ACKData(this, _bufferManage);
        }

        #endregion

        public ACKData Load(byte[] data,int offset,int count)
        {
            var t = this.Take();

            t.Load(data,offset,count);

            return t;
        }

        public ArraySegment<byte> BuildBytes(int connectID,short[] ackList)
        {
            var buff = _bufferManage.TakeBuffer(ackList.Length * 2 + 9);// new byte[_ackList.Length * 2 + 9];
            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.DataACK);
            bs.Write(BitConverter.GetBytes(connectID));
            bs.WriteByte((byte)ackList.Length);

            foreach (var ackIndex in ackList)
            {
                bs.Write(BitConverter.GetBytes(ackIndex));
            }

            bs.Write(buff.GetCRCCodeBytes(0, ackList.Length * 2 + 7));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, ackList.Length * 2 + 9);
        }

        public ArraySegment<byte> BuildBytes(int connectID, short ackIndex)
        {
            var buff = _bufferManage.TakeBuffer(11);// new byte[_ackList.Length * 2 + 9];
            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.DataACK);
            bs.Write(BitConverter.GetBytes(connectID));
            bs.WriteByte(1);

            bs.Write(BitConverter.GetBytes(ackIndex));
  
            bs.Write(buff.GetCRCCodeBytes(0, 9));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, 11);
        }

    }

    internal class ACKData:IRecyclable
    {
        private int _connectID = 0;
        private short[] _ackList = null;
        private ACKDataPool _pool = null;
        private BufferManager _bufferManage = null;

        public int ConnectID { get { return _connectID; } }
        public short[] ACKList { get { return _ackList; } }

        internal ACKData(ACKDataPool pool, BufferManager bufferManage)
        {
            _pool = pool;
            _bufferManage = bufferManage;
        }


        public void Load(byte[] data, int offset, int count)
        {
            //var connectID = BitConverter.ToInt32(data.Array, data.Offset + 2);

            var indexCount = data[offset + 6];

            if (indexCount <= 0)
            {
                return;
            }

            _ackList = new short[indexCount];

            for (int i = 0; i < indexCount; i++)
            {
                _ackList[i] = BitConverter.ToInt16(data, offset + 7 + i * 2);
            }

            this._connectID = BitConverter.ToInt32(data, offset + 2);

        }

        public  ArraySegment<byte> BuildToBytes()
        {
            var buff = _bufferManage.TakeBuffer(_ackList.Length*2 + 9);// new byte[_ackList.Length * 2 + 9];
            var bs = new ByteStream(buff);

            bs.WriteByte(0x01);
            bs.WriteByte((byte)RUDPCmd.DataACK);
            bs.Write(BitConverter.GetBytes(_connectID));
            bs.WriteByte((byte)_ackList.Length);

            foreach (var ackIndex in _ackList)
            {
                bs.Write(BitConverter.GetBytes(ackIndex));
            }

            bs.Write(buff.GetCRCCodeBytes(0, _ackList.Length * 2 + 7));

            bs.Close();
            bs.Dispose();

            return new ArraySegment<byte>(buff, 0, _ackList.Length * 2 + 9);
        }

        #region Implementation of IDisposable

        public void Dispose()
        {
            _pool.RecycleObject(this);
        }

        #endregion

        #region Implementation of IRecyclable

        public IRecyclablePool<IRecyclable> Pool
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        ///     当对象真正释放的时候，回收器会调用该函数
        /// </summary>
        public void DisposeObject()
        {
            
        }

        #endregion
    }



    internal enum RevItemHandle
    {
        None,
        Received,
        ACK
    }

    internal enum RUDPCmd : byte
    {
        Data = 0x01,

        DataACK = 0x02,

        HandShake_ConnectRequest = 0xF0,
        HandShake_ConnectResponse = 0xF1,
        HandShake_ConnectSuccess = 0xF2,
        HandShake_ConnectSuccessACK = 0xF3,  //在服务器接收到HandShake_ConnectSuccess后,服务器才开始新建连接信息,客户端在接收到该信息,或Data指令后才开始向服务器发送数据

        HandShake_Fin = 0xF4,
        HandShake_Fin_ACK = 0xF5,
        HandShake_FinSendClear = 0xF6,
        HandShake_FinSendClear_ACK = 0xF7,


        //HandShake_ConnectSuccessACK = 0xF3,
        KeepActive = 0xE0,
        KeepActive_ACK = 0xE1,



    }


    //internal class RUDPLink
    //{
    //    private Dictionary<int, ConnectConfig> _cacheConnectConfig = new Dictionary<int, ConnectConfig>(10);

    //    private NewRUDP _udpServer;
    //    private TimerPool _timerPool = null;
    //    private object _lockObj = new object();
    //    private BufferManager _bufferManager = null;

    //    internal RUDPLink(NewRUDP udpServer, BufferManager bufferManager)
    //    {
    //        _udpServer = udpServer;
    //        _timerPool = new TimerPool(2);
    //        _bufferManager = bufferManager;

    //    }

    //    internal RUDPConnection AddConnection(int connectID, int dataPageSize, short windowSize, IPEndPoint remotePoint)
    //    {
    //        try
    //        {
    //            lock (_lockObj)
    //            {
    //                _cacheConnectConfig.Add(connectID, null);

    //                var connectionConfig = new ConnectConfig(this, connectID, windowSize, dataPageSize, remotePoint, _bufferManager);

    //                _cacheConnectConfig[connectID] = connectionConfig;

    //                //_timerPool.Add(2000, SendTimeOutChecker, connectionConfig, true);

    //                return connectionConfig.Item;

    //            }

    //        }
    //        catch (Exception)
    //        {
    //            return null;
    //        }

    //    }

    //    internal void DataReceive(int connectID, byte[] data, int offset, int count)
    //    {
    //        //var connectID = BitConverter.ToInt32(data,offset + 2);

    //        switch (data[offset + 1])
    //        {
    //            case 0x01:
    //            case 0x03:
    //                EnQueueDataItem(connectID, data, offset, count);
    //                break;
    //            case 0x02:
    //                EnQueueACK(connectID, data, offset, count);
    //                break;
    //        }
    //    }

    //    internal bool ContansConnection(int connectID)
    //    {
    //        return _cacheConnectConfig.ContainsKey(connectID);
    //    }

    //    internal int Count
    //    {
    //        get { return _cacheConnectConfig.Count; }
    //    }

    //    internal int[] GetConnectIDList()
    //    {
    //        var idList = _cacheConnectConfig.Keys;

    //        return idList.ToArray();
    //    }

    //    internal RUDPConnection this[int connectID]
    //    {
    //        get
    //        {
    //            var t = _cacheConnectConfig.TryGetValue(connectID);

    //            if (t != null)
    //            {
    //                return t.Item;
    //            }
    //            else
    //            {
    //                return null;
    //            }

    //        }
    //    }


    //    #region "数据接收"

    //    internal void EnQueueDataItem(int connectID, byte[] data, int offset, int count)
    //    {
    //        ConnectConfig connectConfig = null;

    //        if (_cacheConnectConfig.TryGetValue(connectID, out connectConfig))
    //        {
    //            var revItem = RevItemSegment.Load(new ArraySegment<byte>(data, offset, count));

    //            if (revItem == null)
    //            {
    //                return;
    //            }
    //            var handle = connectConfig.RevQueue.EnQueue(revItem);

    //            if (handle == RevItemHandle.None)
    //            {
    //                return;
    //            }

    //            SocketACK(connectConfig.ConnectID, new[] { revItem.Index }, connectConfig.RemotePoint);
    //        }
    //        else
    //        {
    //            return;
    //        }
    //    }


    //    private void SocketACK(int connectID, short[] ackList, IPEndPoint remotePoint)
    //    {
    //        var tempData = ACKData.Create(connectID, ackList);//TODO:进行数据封包

    //        _udpServer.SendData(tempData.Array, tempData.Offset, tempData.Count, remotePoint, (o) =>
    //        {
    //            //TODO:回收tempData.Array
    //        }, null);

    //        //_udpServer._socket.BeginSendTo(tempData.Array, tempData.Offset, tempData.Count, SocketFlags.None,
    //        //                                remotePoint, SocketACKCallback, null);

    //    }

    //    #endregion

    //    #region "数据发送"

    //    internal IAsyncResult BeginSend(int connectID, byte[] data, int offset, int count, AsyncCallback callback, object state)
    //    {
    //        ConnectConfig config = null;

    //        if (_cacheConnectConfig.TryGetValue(connectID, out config))
    //        {
    //            //int tempBagID = Interlocked.Increment(ref _bagID); ;

    //            int tempBagID = config.GetBagID();

    //            config.SendQueue.Enqueue(connectID, tempBagID, data, offset, count);

    //            FillAndSend(config);

    //            var iar = new SendAsyncResult(tempBagID, count, callback, state);

    //            config.AddAsyncResult(tempBagID, iar);

    //            return iar;

    //        }
    //        else
    //        {
    //            throw new Exception("连接不存在");
    //        }

    //    }

    //    internal int EndSend(IAsyncResult iar)
    //    {
    //        var item = (SendAsyncResult)iar;

    //        //if (item.Callback == null)
    //        //{
    //        //    throw new Exception();
    //        //}

    //        ConnectConfig config = null;

    //        if (_cacheConnectConfig.TryGetValue(item.ConnectID, out config))
    //        {
    //            config.RemoveAsyncResult(item.BagID);
    //        }

    //        //Monitor.Enter(_cacheSendSyncResult);

    //        //_cacheSendSyncResult.Remove(item.BagID);

    //        //Monitor.Exit(_cacheSendSyncResult);

    //        return item.DataLength;
    //    }

    //    internal void EnQueueACK(int connectID, byte[] data, int offset, int count)
    //    {
    //        ConnectConfig config = null;

    //        if (_cacheConnectConfig.TryGetValue(connectID, out config))
    //        {
    //            var sendWindow = config.SendQueue._currentSendedWindow;

    //            var ackCount = data[offset + 6];

    //            if (ackCount <= 0 || ackCount * 2 + 9 > count)
    //            {
    //                _bufferManager.ReturnBuffer(data);
    //                return;
    //            }

    //            for (int i = 0; i < ackCount; i += 2)
    //            {
    //                var ackIndex = BitConverter.ToInt16(data, offset + 7 + i);

    //                sendWindow.UpdateValue(ackIndex, (s) =>
    //                {
    //                    s.IsSuccess = true;
    //                });
    //            }


    //            Monitor.Enter(sendWindow);

    //            if (sendWindow.GetByIndex(0).IsSuccess)
    //            {
    //                var sendedCount = sendWindow.Count;

    //                SendDataSegment[] tempSendList = new SendDataSegment[sendedCount];

    //                sendWindow.Values.CopyTo(tempSendList, 0);

    //                Monitor.Exit(sendWindow);

    //                for (int i = 0; i < sendedCount; i++)
    //                {
    //                    var item = tempSendList[i];

    //                    if (!item.IsSuccess)
    //                    {

    //                        break;
    //                    }

    //                    sendWindow.Remove(item.FragmentIndex);

    //                    if (item.IsLastFragment)
    //                    {
    //                        SendAsyncResult iar = config.GetAsyncResult(item.BagID);

    //                        if (iar != null)
    //                        {
    //                            config.Item.OnSendDataCompleted(iar);
    //                        }

    //                    }
    //                }

    //                FillAndSend(config);
    //            }
    //            else
    //            {
    //                Monitor.Exit(sendWindow);
    //            }


    //        }

    //        _bufferManager.ReturnBuffer(data);


    //    }

    //    internal void Close(int connectID)
    //    {

    //    }

    //    private void FillAndSend(ConnectConfig config)
    //    {
    //        var sendWindow = config.SendQueue._currentSendedWindow;

    //        Monitor.Enter(sendWindow);

    //        var sendQueue = config.SendQueue._sendQueue;

    //        var inputCount = config.WindowSize - sendWindow.Count;

    //        if (inputCount > 0 && sendQueue.Count > 0)
    //        {
    //            Monitor.Enter(sendQueue);

    //            for (int i = 0; i < inputCount; i++)
    //            {
    //                SendDataSegment item;

    //                if (sendQueue.TryDequeue(out item))
    //                {
    //                    sendWindow.Add(item.FragmentIndex, item);
    //                    SocketSend(item, config.RemotePoint);
    //                }
    //                else
    //                {
    //                    break;
    //                }
    //            }

    //            Monitor.Exit(sendQueue);
    //        }

    //        Monitor.Exit(sendWindow);
    //    }

    //    private void SocketSend(SendDataSegment item, IPEndPoint remotePoint)
    //    {
    //        var tempData = item.BuildToBytes();//TODO:进行数据封包

    //        _udpServer.SendData(tempData.Array, tempData.Offset, tempData.Count, remotePoint, (o) =>
    //        {
    //            //TODO:回收tempData.Array

    //            var t = (SendDataSegment)o;

    //            if (t != null)
    //            {
    //                item.SendTime = DateTime.Now;
    //            }

    //            _bufferManager.ReturnBuffer(tempData.Array);

    //        }, item);

    //        //_udpServer._socket.BeginSendTo(tempData.Array, tempData.Offset, tempData.Count, SocketFlags.None,
    //        //                                remotePoint, SocketSendCallback, item);

    //        //TODO:回收tempData.Array
    //    }

    //    private void SendTimeOutChecker(object state)
    //    {
    //        var item = (ConnectConfig)state;

    //        if (state == null)
    //        {
    //            return;
    //        }

    //        var sendWindow = item.SendQueue._currentSendedWindow;

    //        Monitor.Enter(sendWindow);

    //        if (sendWindow.Count > 0)
    //        {
    //            var timeOutTime = DateTime.Now.AddSeconds(-10);

    //            foreach (var segment in sendWindow)
    //            {
    //                if (segment.Value.SendTime > timeOutTime)
    //                {
    //                    if (segment.Value.SendedCount > 5)
    //                    {
    //                        //TODO:引发连接中断事件,并停止所有发送检测
    //                    }
    //                    else
    //                    {
    //                        SocketSend(segment.Value, item.RemotePoint);
    //                    }

    //                }
    //            }
    //        }

    //        Monitor.Exit(sendWindow);
    //    }

    //    #endregion
    //}

    //internal enum CmdID : byte
    //{
    //    Unknow = 0x00,
    //    SendCmd = 0x01,
    //    RevACK = 0x02,


    //    HandShake_SYN_ConnectRequest = 0xF0,
    //    HandShake_SYN_ConnectAccept = 0xF1,
    //    HandShake_SYN_ConnectAcceptACK = 0xF2,

    //    KeepActive = 0xE0,
    //    KeepActiveACK = 0xE1


    //}
}
